package heiing.collection.map;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author heiing
 */
public class MapDiff {

    private MapDiff() {}

    /**
     * 根据Key比较两个字典的差异
     * @param <K> Key的类型
     * @param <V> Value的类型
     * @param a 第一个字典
     * @param b 第二个字典
     * @return 返回两个字典的差异。Key在 b 中而不在 a 中的为新值，在 a 中而不在 b 中的为已删除的值，同时在 a 与 b 中且值发生变更的为修改过的值
     */
    public static <K, V> MapDiffResult<K, V> diff(Map<K, V> a, Map<K, V> b) {
        if (null == b || b.isEmpty()) {
            return new MapDiffResult<>(null, a);
        }
        if (null == a || a.isEmpty()) {
            return new MapDiffResult<>(b, null);
        }
        Map<K, V> adds = b.keySet().stream().filter(k -> !a.containsKey(k)).collect(LinkedHashMap::new, (m, k) -> m.put(k, b.get(k)), LinkedHashMap::putAll);
        Map<K, V> dels = a.keySet().stream().filter(k -> !b.containsKey(k)).collect(LinkedHashMap::new, (m, k) -> m.put(k, a.get(k)), LinkedHashMap::putAll);
        MapDiffResult<K, V> ret = new MapDiffResult<>(adds, dels, Math.min(a.size(), b.size()));
        a.keySet().stream().filter(b::containsKey).filter(k -> !Objects.equals(a.get(k), b.get(k))).forEach(k -> ret.putChanged(k, a.get(k), b.get(k)));
        return ret;
    }

}
